<?php
/**
 * 表单基类，统一的实现了检测重复提交和从配置文件加载form
 * @author JU MA
 *
 */
class Application_Form_Base extends Zend_Form {
	
	/**
	 * 表单token的name
	 * @var string
	 */
	const TOKEN_ID = "__form_token__";
	
	/**
	 * 是否开启防止重复提交，默认开启
	 * @var bool
	 */
	protected $_isOpenToken = FALSE;
	
	/**
	 * 配置文件的默认路径 ,基础路径是APPLICATION_PATH
	 * @var string
	 */
	protected $_confDir = "/forms/ini";
	
	
	
	protected $_name; //表单的名字 没用
		
	/**
	 * 构造函数
	 * @param string $name 表单名，注意要对应配置文件名,大小写一致，建议全部小写。
	 * @param max $options 暂时无用
	 */
	public function __construct($name = null, $options = null) {
		if ($name != null) {
			$options = $this->_getConfig($name);
			//配置中是否开启token
			$isToken = $options->get("isopentoken");
			if(!empty($isToken)){
				$this->_isOpenToken = $isToken;
			}
		} else if ($options == null) {
			$options = $this->_getConfig();
		}
		
		//I18n
		$this->setTranslator(Application_Service_I18nvalitorcn::getCn());
		
		//$this->setAttribs(array("class"=>"Zend2"));
		
		parent::__construct($options);
		
		//token
		$this->_isOpenToken && $this->TolenInit();
		
		//class
		foreach ($this as $element){
			$element->setAttrib("class", "ui-widget-content");
		}
	}
	
	/**
	 * 获取配置
	 * @param string $name 表单名
	 * @return Zend_Config_Ini
	 */
	protected function _getConfig($name = null) {
		//检查是否有 configs/form.{formname}.ini
		if ($name == null) {
			$class = get_class($this);
			$name = strtolower(substr($class, strrpos($class, "_") + 1));
		}
		$file = APPLICATION_PATH . "{$this->_confDir}/{$name}.ini";
		//$text = file_get_contents($file);
		if (is_file($file)) {
			$config = new Zend_Config_Ini($file);
			return $config;
		}
	}
	
//	protected function _getConfigFile($name) {
//		$file = APPLICATION_PATH . "/configs/form.{$name}.ini";
//		return $file;
//	}

	/**
	 * token相关初始化
	 * Enter description here ...
	 */
	public function TolenInit(){
        $tokenElement = $this->createElement('hidden',self::TOKEN_ID);
        $tokenElement->addValidator("Formtoken")
        			 ->setRequired(TRUE)
        			 ->setValue($this->getTokenVal())
        			 ->addPrefixPath("Application_Validate",APPLICATION_PATH."/plugins/validators/","VALIDATE");
        			 //->addPrefixPath('Application_Filter', APPLICATION_PATH."/plugins/filters/", "FILTER")
        			 //->addFilter("Formtoken");
        $this->addElement($tokenElement);
    }
	
    private function getTokenVal(){
    	return  md5(time());
    }
    
    /**
     * 设置当前实例的token，如果已经开启token，会生成随机数并赋值。
     * @return Zend_Form_Element
     */
    public function setTokenVal(){
    	$tokenEle = $this->getElement(self::TOKEN_ID);
    	if($tokenEle){
    		return $tokenEle->setValue($this->getTokenVal());
    	}else {
    		return FALSE;
    	}
    }

    /**
     * 获取当前实例的form token 的值，
     * 并非重新生成随机数，而是返回已有的token值
     * @return String
     */
    public function getToken(){
    	return $this->getElement(self::TOKEN_ID)->getValue();
    }
    
    /**
     * 忘了我，下次再找我。
     * 验证时，使用此方法必须配合验证的第二个参数为FALSE。
     * @return void
     * Enter description here ...
     */
    public function forgetMeOnce($token=NULL){
    	$tokenSession = new Application_Validate_Formtoken();
    	$token = $token?$token:$this->getToken();
    	$tokenSession->forgetOnce($token);
    }
    
    /**
     * 永远的忘记我吧....
     * @return boolean
     */
    public function forgetMeForever(){
    	return $this->removeElement(self::TOKEN_ID);
    }

    /**
     * 返回令牌错误，包装msg方法，方便使用
     * @return string
     */
    public function getTokenError(){
    	return $this->getMessages(self::TOKEN_ID);
    }
    
    /**
     * 校验TOKEN，有2个参数，$isNewToken会标识验证后是否更新token
     * @param array $data 被校验的数据 
     * @param boolean $isNewToken 标识验证后是否更新token，默认为true
     * @see Zend_Form::isValid()
     */
    public function isValid($data,$isNewToken = TRUE){
    	$v = parent::isValid($data);    	
    	if($isNewToken){
    		$this->setTokenVal();//更新token，重新生成随机数并赋值。
    	}
    	return $v;    	
    }
    
    /*public function render(){
    	$view = new Zend_View();
    	$view->setScriptPath(APPLICATION_PATH . "/views/scripts/zendedit.phtml");
    	parent::render($view);
    }*/
    
    /**
     * 在返回值里面剔除token字段的值
     * @see Zend_Form::getValues()
     */
    public function getValues(){
    	$data = parent::getValues();
    	unset($data['submit']);
    	unset($data['button']);
    	unset($data[self::TOKEN_ID]);
    	return $data;
    }
    
    /**
     * 隐藏某个项目,原理是删除其有效的装饰器并dispaly none
     * @param Zend_Form_Element | string $element（name） 
     * @return　void
     */
    public function hideElement($element){
    	if(is_string($element)){
    		$element = $this->getElement($element);
    	}
    	if( $element instanceof Zend_Form_Element) {
    		$element->removeDecorator("HtmlTag");
    		$element->removeDecorator("Label");
    		$element->setAttrib("style","display:none");
    	}
    }
    
    /**
     * 清除所有element的HTML装饰器
     * @param Zend_Form_Element|string|NULL $element
     * @return void
     */
    public function clearAllDecorators($element=NULL)
    {
    	if($element == NULL){
    		$this->clearDecorators();
    		foreach ($this as $ele){
    			if ( $ele instanceof Zend_Form_Element){
    				$ele->removeDecorator("HtmlTag");
    				$ele->removeDecorator("Label");
    			}
    		}
    		return ;
    	}
    	if(is_string($element)){
    		$element = $this->getElement($element);
    	}
    	if( $element instanceof Zend_Form_Element) {
    		$element->removeDecorator("HtmlTag");
    		$element->removeDecorator("Label");
    	}
    }
}